﻿using System.Collections;
using System.Linq;
using MemoDb.Tests.Model.Collections;
using NUnit.Framework;

namespace MemoDb.Tests
{
    [TestFixture]
    public class CascadeDeleteOrphansTests
    {
        [Test]
        public void ShouldDeleteCollectionIfConfigured()
        {
            var memo = new Memo(deleteOrphansByCascadeByDefault: true)
                .Map<Parent<Child[]>>()
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Child[]>
            {
                Id = 1,
                Name = "parent",
                Children = new[] { child }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Child[]>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Child[]>>());
                CollectionAssert.IsEmpty(s.Query<Child>());
            }
        }

        [Test]
        public void ByDefaultShouldNotDeleteCollection()
        {
            var memo = new Memo()
                .Map<Parent<Child[]>>()
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Child[]>
            {
                Id = 1,
                Name = "parent",
                Children = new[] { child }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Child[]>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Child[]>>());
                Assert.AreEqual(1, s.Query<Child>().Count());
            }
        }
        [Test]
        public void ShouldDeleteCollectionIfConfiguredExplicitly()
        {
            var memo = new Memo()
                .Map<Parent<Child[]>>( c=>c.CasacadeDeleteOrphans(x=>x.Children))
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Child[]>
            {
                Id = 1,
                Name = "parent",
                Children = new[] { child }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Child[]>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Child[]>>());
                CollectionAssert.IsEmpty(s.Query<Child>());
            }
        }

        [Test]
        public void ShouldNotDeleteCollectionIfConfiguredExplicitly()
        {
            var memo = new Memo(deleteOrphansByCascadeByDefault:true)
                                .Map<Parent<Child[]>>(c => c.CasacadeDeleteOrphans(x => x.Children,false))
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Child[]>
            {
                Id = 1,
                Name = "parent",
                Children = new[] { child }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Child[]>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Child[]>>());
                Assert.AreEqual(1, s.Query<Child>().Count());
            }
        }
        
        [Test]
        public void ByDefaultShouldNotDeleteDictionaryKeys()
        {
            var memo = new Memo()
                .Map<Parent<Hashtable>>()
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Hashtable>
            {
                Id = 1,
                Name = "parent",
                Children = new Hashtable
            {
                { child, 1 }
            }
        };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Hashtable>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Hashtable>>());
                Assert.AreEqual(1, s.Query<Child>().Count());
            }
        }
        [Test]
        public void ShouldDeleteDictionaryKeysIfConfiguredExplicitly()
        {
            var memo = new Memo()
                .Map<Parent<Hashtable>>(c => c.CasacadeDeleteOrphans(x => x.Children))
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Hashtable>
            {
                Id = 1,
                Name = "parent",
                Children = new Hashtable { {child,1} }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Hashtable>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Hashtable>>());
                CollectionAssert.IsEmpty(s.Query<Child>());
            }
        }




        [Test]
        public void ByDefaultShouldNotDeleteDictionaryValues()
        {
            var memo = new Memo()
                .Map<Parent<Hashtable>>()
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Hashtable>
            {
                Id = 1,
                Name = "parent",
                Children = new Hashtable
            {
                {  1,child }
            }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Hashtable>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Hashtable>>());
                Assert.AreEqual(1, s.Query<Child>().Count());
            }
        }
        [Test]
        public void ShouldDeleteDictionaryValuesIfConfiguredExplicitly()
        {
            var memo = new Memo()
                .Map<Parent<Hashtable>>(c => c.CasacadeDeleteOrphans(x => x.Children))
                .Map<Child>();

            var child = new Child
            {
                Id = 1,
                Name = "child",
            };

            var parent = new Parent<Hashtable>
            {
                Id = 1,
                Name = "parent",
                Children = new Hashtable { { 1, child } }
            };

            using (var s = memo.CreateSession())
            {
                s.Insert(child);
                s.Insert(parent);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                var test = s.GetById<Parent<Hashtable>>(parent.Id);
                s.Delete(test);
                s.Flush();
            }

            using (var s = memo.CreateSession())
            {
                CollectionAssert.IsEmpty(s.Query<Parent<Hashtable>>());
                CollectionAssert.IsEmpty(s.Query<Child>());
            }
        }
    }


}
